/**
 * activeData.js
 * 获取活跃热力图的相关数据
 *
 * created by qiuwei
 * version 1.0.0
 * 2016年04月06日
 */

import * as CONSTANTS from '../../constants/API';
import rp from '../requestProxy';
import DataAccessor, { ENUM_TIME_UNIT, ENUM_DATA_TYPE } from '../dao/DataAccessor';
import { HTTP_RESULT } from '../../constants/protocol';
import { REPLY_DATA } from '../../constants/replyData';
import cloneDeep from 'lodash/cloneDeep';

// API服务端地址
const url = `${CONSTANTS.HOST}${CONSTANTS.DATA_PACKAGE_ON_SERVER}`;


const STUDENT = 'student', // student_id
	  TEACHER = 'teacher', // teacher_id
	  FIELD_STUDENT = `${STUDENT}_id`,
	  FILED_TEACHER = `${TEACHER}_id`,
	  // 在线学生数
	  ACTION_STUDENT = 'action', 
	  // 在线教师
	  ACTION_TEACHER = 'action',
	  // 提交作业学生
	  SUBMITS = 'homeworkanswer', // student_id
	  // 布置作业教师 
	  FIXUPS = 'homework'; // teacher_id

/**
 * 获取活跃热力图城市视图基础数据
 * @public
 * @param  {string} options.cityId       城市ID
 * @param  {string} options.cityName     城市名称
 * @param  {string} options.provinceId   省份ID
 * @param  {string} options.provinceName 省份名称
 * @param  {string} options.startDate    开始日期范围字符串形式yyyy-mm-dd
 * @param  {string} options.endDate      结束日期范围字符串形式yyyy-mm-dd
 * @param  {array} options.subjects      科目数组
 * @param  {array} options.grades        年级数组
 * @return {promise}                     基础数据
 */
export function cityCount({
	cityId, cityName, 
	provinceId, provinceName, 
	startDate, endDate, subjects, grades}) {

	let dataObjects = cityData(cityId, provinceId, startDate, endDate, subjects, grades);

	dataObjects = dataObjects.map((item) => item.timeUnit(ENUM_TIME_UNIT.NONE).packageType('').jsonObject());

	return rp.post(url, dataObjects).then((result) => {
		if (result.code === HTTP_RESULT.SUCCESS) {

			return Object.assign({}, REPLY_DATA, result, {
				code: HTTP_RESULT.SUCCESS,
				data: packageData(cityName, provinceName, result.data)
			});
		}

		return result;
	});
}

/**
 * 获取活跃热力图区县视图基础数据
 * @public
 * @param  {string} options.countyId     区县ID
 * @param  {string} options.countyName   区县名称
 * @param  {string} options.cityId   	 城市ID
 * @param  {string} options.cityName 	 城市名称
 * @param  {string} options.startDate    开始日期范围字符串形式yyyy-mm-dd
 * @param  {string} options.endDate      结束日期范围字符串形式yyyy-mm-dd
 * @param  {array} options.subjects      科目数组
 * @param  {array} options.grades        年级数组
 * @return {promise}                     基础数据
 */
export function countyCount({
	countyId, countyName, 
	cityId, cityName, 
	startDate, endDate, subjects, grades}) {

	let dataObjects = countyData(countyId, cityId, startDate, endDate, subjects, grades);

	dataObjects = dataObjects.map((item) => item.timeUnit(ENUM_TIME_UNIT.NONE).packageType('').jsonObject());

	return rp.post(url, dataObjects).then((result) => {
		if (result.code === HTTP_RESULT.SUCCESS) {
			
			return Object.assign({}, REPLY_DATA, result, {
				code: HTTP_RESULT.SUCCESS,
				data: packageData(countyName, cityName, result.data)
			});
		}

		return result;
	});
}

/**
 * 获取活跃热力图区学校图基础数据
 * @public
 * @param  {string} options.schoolId     学校ID
 * @param  {string} options.schoolName   学校名称
 * @param  {string} options.countyId   	 区县ID
 * @param  {string} options.countyName 	 区县名称
 * @param  {string} options.startDate    开始日期范围字符串形式yyyy-mm-dd
 * @param  {string} options.endDate      结束日期范围字符串形式yyyy-mm-dd
 * @param  {array} options.subjects      科目数组
 * @param  {array} options.grades        年级数组
 * @return {promise}                     基础数据
 */
export function schoolCount({
	schoolId, schoolName, 
	countyId, countyName, 
	startDate, endDate, subjects, grades}) {

	let dataObjects = schoolData(schoolId, countyId, startDate, endDate, subjects, grades);

	dataObjects = dataObjects.map((item) => item.timeUnit(ENUM_TIME_UNIT.NONE).packageType('').jsonObject());

	// console.log(JSON.stringify(dataObjects));

	return rp.post(url, dataObjects).then((result) => {
		if (result.code === HTTP_RESULT.SUCCESS) {
			
			return Object.assign({}, REPLY_DATA, result, {
				code: HTTP_RESULT.SUCCESS,
				data: packageData(schoolName, countyName, result.data)
			});
		}

		return result;
	});
}

/**
 * 获取活跃热力图城市视图图表数据
 * @public
 * @param  {string} options.cityId    城市ID
 * @param  {string} options.startDate 开始日期范围字符串形式yyyy-mm-dd
 * @param  {string} options.endDate   结束日期范围字符串形式yyyy-mm-dd
 * @param  {array}  options.subjects  科目数组
 * @param  {array}  options.grades    年级数组	
 * @return {promise}                  图表数据
 */
export function cityChart({
	cityId, 
	startDate, endDate, subjects, grades }) {

	let dataObjects = getObjects(startDate, endDate, subjects, grades);
	dataObjects = dataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT)
			item.city(cityId, STUDENT).multiUnit(`${STUDENT}-county_id`);
		else
			item.city(cityId, TEACHER).multiUnit(`${TEACHER}-county_id`);

		return item.timeUnit(ENUM_TIME_UNIT.NONE).packageType('').jsonObject();
	});

	return rp.post(url, dataObjects).then((result) => {
		if (result.code === HTTP_RESULT.SUCCESS) {
			let data = combine(result.data, 'show_name', 'result');

			return Object.assign({}, REPLY_DATA, result, {
				code: HTTP_RESULT.SUCCESS,
				data
			})
		}

		return result;
	});
}

/**
 * 获取活跃热力图城市视图图表数据
 * @public
 * @deprecated 暂时废弃
 * @param  {string} options.cityId    城市ID
 * @param  {string} options.startDate 开始日期范围字符串形式yyyy-mm-dd
 * @param  {string} options.endDate   结束日期范围字符串形式yyyy-mm-dd
 * @param  {array}  options.subjects  科目数组
 * @param  {array}  options.grades    年级数组	
 * @return {promise}                  图表数据
 */
export function countyChart({
	countyId, 
	startDate, endDate, subjects, grades }) {

	let dataObjects = getObjects(startDate, endDate, subjects, grades);
	dataObjects = dataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT)
			item.county(countyId, STUDENT).multiUnit(`${STUDENT}-school_id`);
		else
			item.county(countyId, TEACHER).multiUnit(`${TEACHER}-school_id`);

		return item.timeUnit(ENUM_TIME_UNIT.NONE).packageType('').jsonObject();
	});

	return rp.post(url, dataObjects).then((result) => {
		if (result.code === HTTP_RESULT.SUCCESS) {
			let data = combine(result.data, 'show_name', 'result');

			return Object.assign({}, REPLY_DATA, result, {
				code: HTTP_RESULT.SUCCESS,
				data
			})
		}

		return result;
	});
}

/**
 * 获取活跃热力图城市数据详情
 * @public
 * @param     {String}                 options.provinceId 省ID
 * @param     {String}                 options.cityId     城市ID
 * @param     {String}                 options.startDate  开始时间
 * @param     {String}                 options.endDate    结束时间
 * @param     {String}                 options.grades     年级
 * @param     {String}                 options.subjects   学科
 * @return    {Promise}                                   详情数据
 */
export function cityDetail ({ provinceId, cityId, startDate, endDate, grades, subjects, orderBy, desc }) {
	let dataObjects = getObjects(startDate, endDate, subjects, grades);

	dataObjects = dataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT) 
			item.city(cityId, STUDENT).multiUnit(`${STUDENT}-county_id`);
		else
			item.city(cityId, TEACHER).multiUnit(`${TEACHER}-county_id`);

		return item.timeUnit(ENUM_TIME_UNIT.NONE).packageType('').jsonObject();
	});

	return rp.post(url, dataObjects)
		.then(function (result) {
			if(result.code === HTTP_RESULT.SUCCESS) {
				let data = combine(result.data, 'show_name', 'result');
				data = data.map((item) => {
					item.total = item.onlineStudent + item.onlineTeacher;
					return item;
				});
				data = data.map((item) => {
					let _data = item;
					item = [_data.area, _data.total, _data.onlineStudent, _data.onlineTeacher, _data.submits, _data.fixpus];
					return item;
				});


				if(!orderBy || orderBy === 'total') 
					data.sort((a, b) => b[1] - a[1]);
				// else if(orderBy === 'total')
				// 	data.sort((a, b) => b[1] - a[1]);
				else if(orderBy === 'onlineStudent')
					data.sort((a, b) => a[2] - b[2]);
				else if(orderBy === 'onlineTeacher') 
					data.sort((a, b) => a[3] - b[3]);
				else if(orderBy === 'submits')
					data.sort((a, b) => a[4] - b[4]);
				else if(orderBy === 'fixpus')
					data.sort((a, b) => a[5] - b[5]);

				if(desc)
					data.reverse();

				return Object.assign({}, REPLY_DATA, result, {
					code: HTTP_RESULT.SUCCESS,
					data
				});
			}
			return result;
		});
};

/**
 * 获取活跃热力图区县数据详情
 * @public
 * @param     {String}                 options.provinceId 省ID
 * @param     {String}                 options.cityId     城市ID
 * @param     {String}                 options.startDate  开始时间
 * @param     {String}                 options.endDate    结束时间
 * @param     {String}                 options.grades     年级
 * @param     {String}                 options.subjects   学科
 * @return    {Promise}                                   详情数据
 */
export function countyDetail ({ countyId, startDate, endDate, grades, subjects, orderBy, desc }) {
	let dataObjects = getObjects(startDate, endDate, subjects, grades);

	dataObjects = dataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT) 
			item.county(countyId, STUDENT).multiUnit(`${STUDENT}-school_id`);
		else
			item.county(countyId, TEACHER).multiUnit(`${TEACHER}-school_id`);

		return item.timeUnit(ENUM_TIME_UNIT.NONE).packageType('').jsonObject();
	});

	return rp.post(url, dataObjects)
		.then(function (result) {
			if(result.code === HTTP_RESULT.SUCCESS) {
				let data = combine(result.data, 'show_name', 'result');
				data = data.map((item) => {
					item.total = item.onlineStudent + item.onlineTeacher;
					return item;
				});
				data = data.map((item) => {
					let _data = item;
					item = [_data.area, _data.total, _data.onlineStudent, _data.onlineTeacher, _data.submits, _data.fixpus];
					return item;
				});

				if(!orderBy || orderBy === 'total') 
					data.sort((a, b) => b[1] - a[1]);
				else if(orderBy === 'onlineStudent')
					data.sort((a, b) => a[2] - b[2]);
				else if(orderBy === 'onlineTeacher') 
					data.sort((a, b) => a[3] - b[3]);
				else if(orderBy === 'submits')
					data.sort((a, b) => a[4] - b[4]);
				else if(orderBy === 'fixpus')
					data.sort((a, b) => a[5] - b[5]);

				if(desc)
					data.reverse();

				return Object.assign({}, REPLY_DATA, result, {
					code: HTTP_RESULT.SUCCESS,
					data
				});
			}
			return result;
		});
};

/**
 * 打包数据
 * @private
 * @param  {string} areaName       地域名称
 * @param  {string} parentAreaName 上级地域名称
 * @param  {array}  data           数据集合
 * @return {array}                 二维数组
 */
function packageData(areaName, parentAreaName, data) {
	let [students, teachers, submits, fixups,
		parentStudents, parentTeachers, parentSubmits, parentFixups ]
		= data;

	let results = [
		[areaName, students[0].result, teachers[0].result, submits[0].result, fixups[0].result],
		[parentAreaName, parentStudents[0].result, parentTeachers[0].result, parentSubmits[0].result, parentFixups[0].result]
	];

	return results;
}

/**
 * 获取城市视图查询参数
 * @private
 * @param  {string} cityId     城市ID
 * @param  {string} provinceId 省份ID
 * @param  {string} startDate  开始日期
 * @param  {string} endDate    结束日期
 * @param  {array}  subjects   科目数组
 * @param  {array}  grades     年级数组
 * @return {array}            查询参数数组
 */
function cityData(cityId, provinceId, startDate, endDate, subjects, grades) {
	let cityDataObjects = getObjects(startDate, endDate, subjects, grades);
	let provinceDataObjects = cloneDeep(cityDataObjects);

	// 添加城市标识和省份标识
	cityDataObjects = cityDataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT)
			return item.city(cityId, STUDENT)
		else
			return item.city(cityId, TEACHER);
	});
	provinceDataObjects = provinceDataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT)
			return item.province(provinceId, STUDENT);
		else
			return item.province(provinceId, TEACHER);
	});

	return [...cityDataObjects, ...provinceDataObjects];
}

/**
 * 获取区县视图查询参数
 * @private
 * @param  {string} countyId   区县ID
 * @param  {string} cityId	   城市ID
 * @param  {string} startDate  开始日期
 * @param  {string} endDate    结束日期
 * @param  {array}  subjects   科目数组
 * @param  {array}  grades     年级数组
 * @return {array}            查询参数数组
 */
function countyData(countyId, cityId, startDate, endDate, subjects, grades) {
	let countyDataObjects = getObjects(startDate, endDate, subjects, grades);
	let cityDataObjects = cloneDeep(countyDataObjects);

	// 添加区县标识和城市标识
	countyDataObjects = countyDataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT)
			return item.county(countyId, STUDENT)
		else
			return item.county(countyId, TEACHER);
	});
	cityDataObjects = cityDataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT)
			return item.city(cityId, STUDENT);
		else
			return item.city(cityId, TEACHER);
	});

	return [...countyDataObjects, ...cityDataObjects];
}

/**
 * 获取区学校图查询参数
 * @private
 * @param  {string} schoolId   学校ID
 * @param  {string} countyId   区县ID
 * @param  {string} startDate  开始日期
 * @param  {string} endDate    结束日期
 * @param  {array}  subjects   科目数组
 * @param  {array}  grades     年级数组
 * @return {array}            查询参数数组
 */
function schoolData(schoolId, countyId, startDate, endDate, subjects, grades) {
	let schoolDataObjects = getObjects(startDate, endDate, subjects, grades);
	let countyDataObjects = cloneDeep(schoolDataObjects);

	// 添加区县标识和城市标识
	schoolDataObjects = schoolDataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT)
			return item.school(schoolId, STUDENT)
		else
			return item.school(schoolId, TEACHER);
	});
	countyDataObjects = countyDataObjects.map((item) => {
		if (item._fieldName == FIELD_STUDENT)
			return item.county(countyId, STUDENT);
		else
			return item.county(countyId, TEACHER);
	});

	return [...schoolDataObjects, ...countyDataObjects];
}

/**
 * 获得拥有基础结构的查询参数, 可以进一步构建查询参数
 * @private
 * @param  {string} startDate 开始日期
 * @param  {string} endDate   结束日期
 * @param  {array}  subjects  科目数组
 * @param  {array}  grades    年级数组
 * @return {array}           查询参数数组
 */
function getObjects(startDate, endDate, subjects, grades) {
	let students = getObjectsByTitle(ACTION_STUDENT, STUDENT, startDate, endDate, null, grades);
	let teachers = getObjectsByTitle(ACTION_TEACHER, TEACHER, startDate, endDate, subjects, grades);
	let submits = getObjectsByTitle(SUBMITS, STUDENT, startDate, endDate, null, grades);
	let fixups = getObjectsByTitle(FIXUPS, TEACHER, startDate, endDate, subjects, grades);

	return [students, teachers, submits, fixups];
}

/**
 * 根据提供的表名与字段名创建查询参数
 * @private
 * @param  {string} title     表名
 * @param  {string} field     字段名
 * @param  {string} startDate 开始日期
 * @param  {string} endDate   结束日期
 * @param  {array}  subjects  科目数组
 * @param  {array}  grades    年级数组
 * @return {DataAccessor}           数据访问参数对象
 */
function getObjectsByTitle(title, field, startDate, endDate, subjects, grades) {
	let dao = new DataAccessor(title, `${field}_id`)
		.dateRange(startDate, endDate)
		.dataType(ENUM_DATA_TYPE.COUNT)
		.timeUnit(ENUM_TIME_UNIT.NONE);

	if (subjects && subjects.length)
		dao.subject(subjects, field);
	if (grades && grades.length)
		dao.grade(grades, field);

	return dao;
}

/**
 * 合并数据
 * @private
 * @param  {array}  arr       原始数据
 * @param  {string} keyName   键名
 * @param  {string} valueName 值名
 * @return {array}            新数组
 */
function combine(arr, keyName, valueName) {
	let map = {}, item, current; 
	// item is [0, 0, 0, 0];
	// map is key: [0, 0, 0, 0];

	// 顺序分别是, 学生数据, 教师数据, 提交作业学生数据, 布置作业教师数据
	for (let columnIndex = 0; columnIndex < arr.length; columnIndex++) {
		current = arr[columnIndex];

		for (let rowIndex = 0; rowIndex < current.length; rowIndex++) {
			item = current[rowIndex];

			if (!map[item[keyName]])
				map[item[keyName]] = [0, 0, 0, 0];

			map[item[keyName]][columnIndex] = parseInt(item[valueName]);
		}
	}

	let entries = Object.entries(map);
	return entries.map(([key, value]) => ({ 
			area: key,
			onlineStudent: value[0],
			onlineTeacher: value[1],
			submits: value[2],
			fixpus: value[3]
		}));
}
